﻿using System;
using System.IO;
using System.Threading.Tasks;
using System.Web;
using FastEmit;
using Microsoft.Owin;

namespace FastApi
{
    public static class FastExtensions
    {
        public static Task WriteFileAsync(this IOwinResponse response, string filePath, string fileName = null)
        {
            response.ContentType = "application/octet-stream";
            if (string.IsNullOrEmpty(fileName))
            {
                fileName = Path.GetFileName(filePath);
            }
            fileName = HttpUtility.UrlEncode(fileName);
            response.Headers["Content-disposition"] = $"attachment;filename={fileName}";
            return response.WriteAsync(File.ReadAllBytes(filePath));
        }

        public static Task WriteFileAsync(this IOwinResponse response, byte[] bytes, string fileName = null)
        {
            response.ContentType = "application/octet-stream";
            if (!string.IsNullOrEmpty(fileName))
            {
                fileName = HttpUtility.UrlEncode(fileName);
                response.Headers["Content-disposition"] = $"attachment;filename={fileName}";
            }
            return response.WriteAsync(bytes);
        }

        public static object BindModel(this IReadableStringCollection query, Type type)
        {
            var obj = ConstructorExtensions.CreateInstance(type);
            foreach (var item in type.GetProperties())
            {
                string val = query[item.Name];
                if (item.PropertyType == typeof(string))
                {
                    PropertyExtensions.SetPropertyValue(obj, item.Name, val);
                }
                else
                {
                    if (!string.IsNullOrEmpty(val))
                    {
                        var newVal = TypeConverter.Get(item.PropertyType, val);
                        PropertyExtensions.SetPropertyValue(obj, item.Name, newVal);
                    }
                }
            }
            return obj;
        }

        public static T BindModel<T>(this IReadableStringCollection query)
        {
            return (T)BindModel(query, typeof(T));
        }

        public static void BindToModel(this IReadableStringCollection query, object model)
        {
            var type = model.GetType();
            foreach (var item in type.GetProperties())
            {
                string val = query[item.Name];
                if (item.PropertyType == typeof(string))
                {
                    PropertyExtensions.SetPropertyValue(model, item.Name, val);
                }
                else
                {
                    if (!string.IsNullOrEmpty(val))
                    {
                        var newVal = TypeConverter.Get(item.PropertyType, val);
                        PropertyExtensions.SetPropertyValue(model, item.Name, newVal);
                    }
                }
            }
        }

        public static object BindModel(this IFormCollection form, Type type)
        {
            var obj = ConstructorExtensions.CreateInstance(type);
            foreach (var item in type.GetProperties())
            {
                string val = form[item.Name];
                if (item.PropertyType == typeof(string))
                {
                    PropertyExtensions.SetPropertyValue(obj, item.Name, val);
                }
                else
                {
                    if (!string.IsNullOrEmpty(val))
                    {
                        var newVal = TypeConverter.Get(item.PropertyType, val);
                        PropertyExtensions.SetPropertyValue(obj, item.Name, newVal);
                    }
                }
            }
            return obj;
        }

        public static T BindModel<T>(this IFormCollection form)
        {
            return (T)BindModel(form, typeof(T));
        }

        public static void BindToModel(this IFormCollection form, object model)
        {
            var type = model.GetType();
            foreach (var item in type.GetProperties())
            {
                string val = form[item.Name];
                if (item.PropertyType == typeof(string))
                {
                    PropertyExtensions.SetPropertyValue(model, item.Name, val);
                }
                else
                {
                    if (!string.IsNullOrEmpty(val))
                    {
                        var newVal = TypeConverter.Get(item.PropertyType, val);
                        PropertyExtensions.SetPropertyValue(model, item.Name, newVal);
                    }
                }
            }
        }


    }
}
